package com.cfweb.api;

import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

import javax.servlet.http.HttpSession;

import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import com.cfweb.controller.LoginHandler;
import com.cfweb.dao.CfUserMapper;
import com.cfweb.pojo.OauthToken;
import com.cfweb.util.CloudFoundryClientUtil;
import com.cfweb.util.MutiThreadUtil;
import com.cfweb.util.PropertiesUtil;
import com.cfweb.util.ResourceCall;
import com.cfweb.util.StringUtil;

/**
 * 获取首页统计信息
 * 
 * @author (tiandi，minxianliu,yufangjiang) Dec 2, 2014
 */
public class BasicInfoApi {
  /**
   * 获取首页统计信息
   * 
   * @param session
   * @param mapper
   * @return
   * @throws Exception
   */
  @SuppressWarnings("unchecked")
  public static Map<String, Object> getBasicInfo(HttpSession session, CfUserMapper mapper)
      throws Exception {
    Map<String, Object> mapRes = new HashMap<String, Object>();

    ThreadPoolExecutor executor = MutiThreadUtil.getExecutorService();

    HttpClient httpClient = new DefaultHttpClient();
    String org = (String) session.getAttribute(LoginHandler.ORG);
    String space = (String) session.getAttribute(LoginHandler.SPACE);
    String spaceGuid = null;
    if (!StringUtil.isEmpty(org) && !StringUtil.isEmpty(space)) {
      spaceGuid = UserApi.get_space_id(session, org, space);
    }
    OauthToken token = (OauthToken)session.getAttribute(LoginHandler.TOKEN);
    String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
    if (!StringUtil.isEmpty(spaceGuid)) {
      // apps
      String listAppUrl = host + "/v2/spaces/" + spaceGuid + "/apps?inline-relations-depth=1";
      HttpGet httpGetApps = new HttpGet(listAppUrl);
      CloudFoundryClientUtil.setAccessHeaders(httpGetApps, session);
      // routes
      String routeUrl = host + "/v2/spaces/" + spaceGuid + "/routes?inline-relations-depth=1";
      HttpGet httpGetRoute = new HttpGet(routeUrl);
      CloudFoundryClientUtil.setAccessHeaders(httpGetRoute, session);

      // services
      String listAllServiceUrl = host
          + "/v2/spaces/"
          + spaceGuid
          + "/service_instances?inline-relations-depth=1&return_user_provided_service_instances=true";
      HttpGet httpGetService = new HttpGet(listAllServiceUrl);
      CloudFoundryClientUtil.setAccessHeaders(httpGetService, session);
      try {
        // ************************* application informations
        // ***********************
        Future<Map<String, Object>> resourcesRes = executor.submit(new ResourceCall(httpClient,
            httpGetApps, ResourceCall.HTTP, ((URL) session.getAttribute(LoginHandler.TARGET))
                .toString(), token.getTokenType()+" "+token.getToken(session)));
        if (resourcesRes != null) {
          List<Map<String, Object>> resources = (List<Map<String, Object>>) resourcesRes.get().get(
              "list");
          mapRes.put("applicationNum", resources.size());

          String[] stateKeys = { "entity", "state" };
          String[] memoryKeys = { "entity", "memory" };
          int updating = 0;
          int started = 0;
          int stopped = 0;
          int memoryUsed = 0;
          for (Map<String, Object> appRes : resources) {
            String state = (String) ((Map<String, Object>) appRes.get(stateKeys[0]))
                .get(stateKeys[1]);
            if ("UPDATING".equals(state)) {
              updating++;
            } else if ("STARTED".equals(state)) {
              started++;
            } else {
              stopped++;
            }

            memoryUsed += (int) ((Map<String, Object>) appRes.get(memoryKeys[0]))
                .get(memoryKeys[1]);
          }
          mapRes.put("updating", updating);
          mapRes.put("started", started);
          mapRes.put("stopped", stopped);
          mapRes.put("memoryUsed", memoryUsed);

          // ************************* user informations
          // ***********************
          mapRes.put("orgnization", LoginHandler.ORG);
          mapRes.put("space", LoginHandler.SPACE);

          // ************************* services informations
          // ***********************
          Future<Map<String, Object>> serviceFu = executor.submit(new ResourceCall(httpClient,
              httpGetService, ResourceCall.HTTP, ((URL) session.getAttribute(LoginHandler.TARGET))
                  .toString(), token.getTokenType()+" "+token.getToken(session)));
          if (serviceFu != null) {
            mapRes.put("serviceNum", serviceFu.get().get("resource_size"));
          }
          // ************************* route routesNum
          // *************************
          Future<Map<String, Object>> routeFu = executor.submit(new ResourceCall(httpClient,
              httpGetRoute, ResourceCall.HTTP, ((URL) session.getAttribute(LoginHandler.TARGET))
                  .toString(),token.getTokenType()+" "+token.getToken(session)));
          if (routeFu != null) {
            mapRes.put("routesNum", routeFu.get().get("resource_size"));
          }
        }
      } catch (Exception e) {
        throw e;
      } finally {
        if (httpGetRoute != null) {
          httpGetRoute.abort();
        }
        if (httpGetService != null) {
          httpGetService.abort();
        }
        if (httpGetApps != null) {
          httpGetApps.abort();
        }
      }

    }

    Map<String, Object> orgDetail = OrgApi.getParticularOrg(org, session);
    if (orgDetail != null) {
      // quotas
      String quotaUrl = host
          + (String) ((Map<String, Object>) orgDetail.get("entity")).get("quota_definition_url");
      HttpGet httpGetQuota = new HttpGet(quotaUrl);
      CloudFoundryClientUtil.setAccessHeaders(httpGetQuota, session);
      try {

        // ************************* quota informations
        // ***********************
        Future<Map<String, Object>> quotaFu = executor.submit(new ResourceCall(httpClient,
            httpGetQuota, ResourceCall.GETITEM, ((URL) session.getAttribute(LoginHandler.TARGET))
                .toString(), token.getTokenType()+" "+token.getToken(session)));
        if (quotaFu != null) {
          Map<String, Object> data = (Map<String, Object>) quotaFu.get().get("entity");
          mapRes.put("memoryAll", data.get("memory_limit"));
          mapRes.put("routesAll", data.get("total_routes"));
          mapRes.put("serviceAll", data.get("total_services"));
        }
      } catch (Exception e) {
        throw e;
      } finally {
        if (httpGetQuota != null) {
          httpGetQuota.abort();
        }

        if (httpClient != null) {
          httpClient.getConnectionManager().shutdown();
        }

      }
    }
    //获取存在的org
    mapRes.put("orgNum", 23);
    mapRes.put("orgAll", PropertiesUtil.getProperty("orgall"));
    return mapRes;
  }
  
  /**
	 * 获取首页统计信息
	 * 
	 * @param session
	 * @param mapper
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static Map<String, Object> getAllBasicInfo(HttpSession session) throws Exception {

		Map<String, Object> mapRes = new HashMap<String, Object>();

		ThreadPoolExecutor executor = MutiThreadUtil.getExecutorService();

		HttpClient httpClient = new DefaultHttpClient();
		OauthToken token = (OauthToken) session.getAttribute(LoginHandler.TOKEN);
		String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
		// apps
		String listAppUrl = host + "/v2/apps?inline-relations-depth=1";
		HttpGet httpGetApps = new HttpGet(listAppUrl);
		CloudFoundryClientUtil.setAccessHeaders(httpGetApps, session);
		// routes
		String routeUrl = host + "/v2/routes?inline-relations-depth=1";
		HttpGet httpGetRoute = new HttpGet(routeUrl);
		CloudFoundryClientUtil.setAccessHeaders(httpGetRoute, session);

		// services
		String listAllServiceUrl = host + "/v2/service_instances?inline-relations-depth=1";
		HttpGet httpGetService = new HttpGet(listAllServiceUrl);
		CloudFoundryClientUtil.setAccessHeaders(httpGetService, session);
		try {
			// ************************* application informations
			// ***********************
			Future<Map<String, Object>> resourcesRes = executor.submit(new ResourceCall(httpClient, httpGetApps,
					ResourceCall.HTTP, ((URL) session.getAttribute(LoginHandler.TARGET)).toString(),
					token.getTokenType() + " " + token.getToken(session)));
			if (resourcesRes != null) {
				List<Map<String, Object>> resources = (List<Map<String, Object>>) resourcesRes.get().get("list");
				mapRes.put("applicationNum", resources.size());

				String[] stateKeys = { "entity", "state" };
				String[] memoryKeys = { "entity", "memory" };
				int updating = 0;
				int started = 0;
				int stopped = 0;
				int memoryUsed = 0;
				for (Map<String, Object> appRes : resources) {
					String state = (String) ((Map<String, Object>) appRes.get(stateKeys[0])).get(stateKeys[1]);
					if ("UPDATING".equals(state)) {
						updating++;
					} else if ("STARTED".equals(state)) {
						started++;
					} else {
						stopped++;
					}

					memoryUsed += (int) ((Map<String, Object>) appRes.get(memoryKeys[0])).get(memoryKeys[1]);
				}
				mapRes.put("updating", updating);
				mapRes.put("started", started);
				mapRes.put("stopped", stopped);
				mapRes.put("memoryUsed", memoryUsed);

				// ************************* user informations
				// ***********************
				mapRes.put("orgnization", LoginHandler.ORG);
				mapRes.put("space", LoginHandler.SPACE);

				// ************************* services informations
				// ***********************
				Future<Map<String, Object>> serviceFu = executor.submit(new ResourceCall(httpClient, httpGetService,
						ResourceCall.HTTP, ((URL) session.getAttribute(LoginHandler.TARGET)).toString(),
						token.getTokenType() + " " + token.getToken(session)));
				if (serviceFu != null) {
					mapRes.put("serviceNum", serviceFu.get().get("resource_size"));
				}
				// ************************* route routesNum
				// *************************
				Future<Map<String, Object>> routeFu = executor.submit(new ResourceCall(httpClient, httpGetRoute,
						ResourceCall.HTTP, ((URL) session.getAttribute(LoginHandler.TARGET)).toString(),
						token.getTokenType() + " " + token.getToken(session)));
				if (routeFu != null) {
					mapRes.put("routesNum", routeFu.get().get("resource_size"));
				}
			}
		} catch (Exception e) {
			throw e;
		} finally {
			if (httpGetRoute != null) {
				httpGetRoute.abort();
			}
			if (httpGetService != null) {
				httpGetService.abort();
			}
			if (httpGetApps != null) {
				httpGetApps.abort();
			}
		}

		List<Map<String, Object>> orgs = OrgApi.list_orgs(session);
		HttpGet httpGetQuota = null;
		int memoryAll = 0;
		int routesAll = 0;
		int serviceAll = 0;

		try {
			for (Map<String, Object> map : orgs) {
				String org = (String) map.get("name");
				Map<String, Object> orgDetail = OrgApi.getParticularOrg(org, session);
				if (orgDetail != null) {
					// quotas
					String quotaUrl = host
							+ (String) ((Map<String, Object>) orgDetail.get("entity")).get("quota_definition_url");
					httpGetQuota = new HttpGet(quotaUrl);
					CloudFoundryClientUtil.setAccessHeaders(httpGetQuota, session);

					// ************************* quota informations
					// ***********************
					Future<Map<String, Object>> quotaFu = executor.submit(new ResourceCall(httpClient, httpGetQuota,
							ResourceCall.GETITEM, ((URL) session.getAttribute(LoginHandler.TARGET)).toString(),
							token.getTokenType() + " " + token.getToken(session)));

					if (quotaFu != null) {
						Map<String, Object> data = (Map<String, Object>) quotaFu.get().get("entity");
						memoryAll += (int) data.get("memory_limit");
						routesAll += (int) data.get("total_routes");
						serviceAll += (int) data.get("total_services");
					}
				}
			}
			mapRes.put("memoryAll", memoryAll);
			mapRes.put("routesAll", routesAll);
			mapRes.put("serviceAll", serviceAll);
		} catch (Exception e) {
			throw e;
		} finally {
			if (httpGetQuota != null) {
				httpGetQuota.abort();
			}

			if (httpClient != null) {
				httpClient.getConnectionManager().shutdown();
			}

		}
		return mapRes;
	}
}
